package com.whzm.service.impl;

import com.whzm.mapper.ResourcesMapper;
import com.whzm.pojo.*;
import com.whzm.pojo.vo.ResourceDetailVo;
import com.whzm.pojo.vo.ResourcesListVo;
import com.whzm.service.*;
import com.whzm.util.ResponseEntity;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @BelongsProject: rate-of-flow
 * @BelongsPackage: com.whzm.service.impl
 * @Author: 吴严
 * @CreateTime: 2020-08-12 20:16
 * @Description:
 */
@Service
@Transactional
public class ResourcesServiceImpl implements IResourcesService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IRedisService redisService;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ResourcesMapper resourcesMapper;

    @Autowired
    private IResourceImplService implService;

    @Autowired
    private IResourceAreaService areaService;

    @Autowired
    private IResourceCoopService coopService;
//
//    /**
//     * 查询资源,整合了ES，实现mysql和es的读写分离
//     *
//     * @param resourceEntity
//     * @return
//     */
//    @Override
//    public ResponseEntity esQueryAll(ResourceEntity resourceEntity) {
//        if (StringUtils.isEmpty(resourceEntity)) {
//            System.out.println("参数为空");
//            return ResponseEntity.pageSuccess(200, "ok", resourcesMapper.queryAll(0), resourcesMapper.queryAll(0).size());
//        }
//        //查询先查ES
//        List<ResourceESVo> resources = new ArrayList<>();
//        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
//        //构件模糊查询条件
//        //搜索名字中含有jack的文档
//        WildcardQueryBuilder queryBuilder1 = QueryBuilders.wildcardQuery("name", "*" + resourceEntity.getKeyWord() + "*");
//        WildcardQueryBuilder queryBuilder2 = QueryBuilders.wildcardQuery("detail", "*" + resourceEntity.getKeyWord() + "*");
//        if (resourceEntity.getType() != null && resourceEntity.getType() != 0) {
//            WildcardQueryBuilder queryBuilder4 = QueryBuilders.wildcardQuery("type", resourceEntity.getType() + "");
//            boolQueryBuilder.must(queryBuilder4);
//        }
//        //name或者detail中含有keyWord的都将被检索到
//        boolQueryBuilder.should(queryBuilder1);
//        Iterable<ResourceESVo> resourceESVos = resourceEsService.findAll(PageRequest.of(0, 5));
//        resourceESVos.forEach(object -> {
//            resources.add(object);
//            System.out.println("查询结果-------------" + object.toString());
//        });

//        WildcardQueryBuilder wqb = QueryBuilders.wildcardQuery("name", "*" + resourceEntity.getKeyWord() + "*");
//
//        //PageRequest.of(page页数，size每页的数据量)
//        Query query = new NativeSearchQueryBuilder().withQuery(wqb).withPageable(PageRequest.of(0, 5)).build();
//
//        Page<ResourceESVo> resourceESVos = resourceEsService.search(query);
//        System.out.println(resourceESVos.getSize());
//
//        return ResponseEntity.pageSuccess(200, "ok", resources, null);
//    }

    /**
     * 查询资源列表数据
     *
     * @param resourceEntity
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ResponseEntity queryAll(ResourceEntity resourceEntity) {
        if (StringUtils.isEmpty(resourceEntity)) {
            return ResponseEntity.pageSuccess(200, "ok", resourcesMapper.queryAll(0, resourceEntity.getKeyWord()), resourcesMapper.queryAll(0, resourceEntity.getKeyWord()).size());
        }
        List<ResourcesListVo> resources = resourcesMapper.queryAll(resourceEntity.getType(), "%" + resourceEntity.getKeyWord() + "%");
        return selectAndPage(resources, resourceEntity);
    }

    /**
     * 封装了查询结果对条件的筛选以及手动分页的创建
     *
     * @param resources
     * @param resourceEntity
     * @return
     */
    public ResponseEntity selectAndPage(List<ResourcesListVo> resources, ResourceEntity resourceEntity) {
        Integer count = resources.size();
        if (!StringUtils.isEmpty(resourceEntity.getImplIds())) {
//            System.out.println("进入了落地方式条件筛选");
            String[] implStrings = resourceEntity.getImplIds().split(",");
            for (int i = 0; i < resources.size(); i++) {
                List<Implementation> implementations = resources.get(i).getImplementations();
                List<String> implIdList = new ArrayList<>();
                for (Implementation implementation : implementations) {
                    implIdList.add(implementation.getImplementationId());
                }
                for (String implId : implStrings) {
                    if (!implIdList.contains(implId)) {
                        resources.remove(i);
                        i--;  //当list删除数据后，索引会自动更新，所以先减一，for里面再加一，保证元素顺序完整性
                        break;
                    }
                }
            }
        }
        if (!StringUtils.isEmpty(resourceEntity.getAreaIds())) {
//            System.out.println("进入了地区条件筛选");
            String[] areaStrings = resourceEntity.getAreaIds().split(",");
            for (int i = 0; i < resources.size(); i++) {
                List<Area> areas = resources.get(i).getAreas();
                List<String> areaIdList = new ArrayList<>();
                for (Area area : areas) {
                    areaIdList.add(area.getAreaId());
                }
                for (String areaId : areaStrings) {
                    if (!areaIdList.contains(areaId)) {
                        resources.remove(i);
                        i--;  //当list删除数据后，索引会自动更新，所以先减一，for里面再加一，保证元素顺序完整性
                        break;
                    }
                }
            }
        }
        if (!StringUtils.isEmpty(resourceEntity.getCoopIds())) {
//            System.out.println("进入了合作方式条件筛选");
            String[] coopStrings = resourceEntity.getCoopIds().split(",");
            for (int i = 0; i < resources.size(); i++) {
                List<Cooperation> cooperations = resources.get(i).getCooperations();
                List<String> coopIdList = new ArrayList<>();
                for (Cooperation cooperation : cooperations) {
                    coopIdList.add(cooperation.getCooperationId());
                }
                for (String coopId : coopStrings) {
                    if (!coopIdList.contains(coopId)) {
                        resources.remove(i);
                        i--;  //当list删除数据后，索引会自动更新，所以先减一，for里面再加一，保证元素顺序完整性
                        break;
                    }
                }
            }
        }
        List<ResourcesListVo> resourcesListVos = new ArrayList<>();
        //设定页码默认初始值
        Integer page = 1;
        if (resourceEntity.getPage() != null && resourceEntity.getPage() != 0) {
            page = resourceEntity.getPage();
        }
        //设定页面尺寸的默认初始值
        Integer pageSize = 5;
        if (resourceEntity.getPageSize() != null && resourceEntity.getPageSize() != 0) {
            pageSize = resourceEntity.getPageSize();
        }
        //因数据库查询要求是多对多，所以查询出来数据结果集无法分页，需要封装到实体类集合后手动分页
        Integer start = (page - 1) * pageSize;
        Integer end = (page - 1) * pageSize + pageSize;
        end = end < count ? end : count;
        resourcesListVos = resources.subList(start, end);
        return ResponseEntity.pageSuccess(200, "ok", resourcesListVos, count);
    }

//    /**
//     * 添加资源先访问mysql，并发出确认消息，消息成功消费后，将数据同步到Elasticsearch
//     *
//     * @param resourceEntity
//     * @return
//     */
//    @Override
//    public ResponseEntity esAddResource(ResourceEntity resourceEntity) {
//        if (StringUtils.isEmpty(resourceEntity)) {
//            return ResponseEntity.tipsSuccess(500, "操作有误，请重试");
//        }
//        Resources resources = new Resources();
//        String resourceId = "R" + String.valueOf(System.currentTimeMillis() + "" + (int) (Math.random() * 100)).substring(3);
//        //利用spring中的copy对象的方法完成两个对象中相同字段的复制
//        BeanUtils.copyProperties(resourceEntity, resources);
//        resources.setId(resourceId);
//        //将资源对象新增到资源表中
//        Integer add = resourcesMapper.addResource(resources);
//        //资源添加完成后，需要添加与资源信息关联的落地方式，地区，合作方式等信息
//        if (add > 0) {
//            String[] implIds = resourceEntity.getImplIds().split(",");
//            for (String implId : implIds) {
//                ResourceImpl resourceImpl = new ResourceImpl();
//                resourceImpl.setImplementationId(implId);
//                resourceImpl.setResourcesId(resourceId);
//                implService.addResourceImpl(resourceImpl);
//            }
//            String[] areaIds = resourceEntity.getAreaIds().split(",");
//            for (String areaId : areaIds) {
//                ResourceArea resourceArea = new ResourceArea();
//                resourceArea.setAreaId(areaId);
//                resourceArea.setResourcesId(resourceId);
//                areaService.addResourceArea(resourceArea);
//            }
//            String[] coopIds = resourceEntity.getCoopIds().split(",");
//            for (String coopId : coopIds) {
//                ResourceCoop resourceCoop = new ResourceCoop();
//                resourceCoop.setCooperationId(coopId);
//                resourceCoop.setResourcesId(resourceId);
//                coopService.addResourceCoop(resourceCoop);
//            }
//            //新增完成后，从数据库得到此条资源信息
//            ResourcesListVo resourcesListVo = resourcesMapper.getByResourceId(resourceId).get(0);
//            ResourceESVo resourceESVo = new ResourceESVo();
//            BeanUtils.copyProperties(resourcesListVo, resourceESVo);
//            System.out.println("-------------------" + resourceESVo.toString());
//            //将此条资源同步更新到redis中
//            redisTemplate.opsForValue().set(resourceESVo.getId(), resourceESVo);
//            //给rabbitmq监听队列发送消息，mq消费消息后，在es中增加此条资源，实现es和mysql的数据同步
//            rabbitTemplate.convertAndSend("spring-mysql-to-es", resourceESVo.getId() + "-insert");
//            return ResponseEntity.tipsSuccess(200, "添加成功");
//        }
//        return ResponseEntity.tipsSuccess(500, "系统故障，添加失败");
//    }

    /**
     * 新增资源，需要先在mysql中添加，然后将其添加到redis中
     *
     * @param resourceEntity
     * @return
     */
    @Override
    public ResponseEntity addResource(ResourceEntity resourceEntity) {
        if (StringUtils.isEmpty(resourceEntity)) {
            return ResponseEntity.tipsSuccess(500, "操作有误，请重试");
        }
        Resources resources = new Resources();
        String resourceId = "R" + String.valueOf(System.currentTimeMillis() + "" + (int) (Math.random() * 100)).substring(3);
        //利用spring中的copy对象的方法完成两个对象中相同字段的复制
        BeanUtils.copyProperties(resourceEntity, resources);
        resources.setId(resourceId);
        //将资源对象新增到资源表中
        Integer add = resourcesMapper.addResource(resources);
        //资源添加完成后，需要添加与资源信息关联的落地方式，地区，合作方式等信息
        if (add > 0) {
            String[] implIds = resourceEntity.getImplIds().split(",");
            for (String implId : implIds) {
                ResourceImpl resourceImpl = new ResourceImpl();
                resourceImpl.setImplementationId(implId);
                resourceImpl.setResourcesId(resourceId);
                implService.addResourceImpl(resourceImpl);
            }
            String[] areaIds = resourceEntity.getAreaIds().split(",");
            for (String areaId : areaIds) {
                ResourceArea resourceArea = new ResourceArea();
                resourceArea.setAreaId(areaId);
                resourceArea.setResourcesId(resourceId);
                areaService.addResourceArea(resourceArea);
            }
            String[] coopIds = resourceEntity.getCoopIds().split(",");
            for (String coopId : coopIds) {
                ResourceCoop resourceCoop = new ResourceCoop();
                resourceCoop.setCooperationId(coopId);
                resourceCoop.setResourcesId(resourceId);
                coopService.addResourceCoop(resourceCoop);
            }
            ResourceDetailVo resourceDetailVo = resourcesMapper.getById(resourceId).get(0);
            redisTemplate.opsForValue().set(resourceDetailVo.getId(), resourceDetailVo);
            return ResponseEntity.tipsSuccess(200, "添加成功");
        }
        return ResponseEntity.tipsSuccess(500, "系统故障，添加失败");
    }

    /**
     * 更新资源
     *
     * @param resourceEntity
     * @return
     */
    @Override
    public ResponseEntity updateResource(ResourceEntity resourceEntity) {
        redisTemplate.opsForValue().set(resourceEntity.getId(), null, 5L);
        Integer update = resourcesMapper.updateResource(resourceEntity);
        if (update > 0) {
            return ResponseEntity.tipsSuccess(200, "资源修改成功");
        }
        return ResponseEntity.tipsSuccess(500, "系统故障");
    }

    /**
     * 根据资源id查询单条资源数据
     *
     * @param id
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ResponseEntity getById(String id) {
        //查询单条数据，先查redis
        Object obj = redisTemplate.opsForValue().get(id);
        ResourceDetailVo resourceDetailVo = null;
        //判断查询到的数据是否为空，进而选择是否查询mysql
        if (StringUtils.isEmpty(obj)) {
            resourceDetailVo = resourcesMapper.getById(id).get(0);
            //如果redis中没有，则将从mysql中查询到的数据更新到缓存中
            redisTemplate.opsForValue().set(id, resourceDetailVo);
        } else {
            resourceDetailVo = (ResourceDetailVo) obj;
        }
        return ResponseEntity.entitySuccess(200, "ok", resourceDetailVo);
    }

    /**
     * 根据用户id查询当前用户下有多少条相关资源
     * 查询多条资源无法先从redis找
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(readOnly = true)
    public ResponseEntity getByUserId(String userId) {
        List<ResourceDetailVo> resourceDetailVos = resourcesMapper.getByUserId(userId);
        return ResponseEntity.pageSuccess(200, "查询成功", resourceDetailVos, resourceDetailVos.size());
    }

    /**
     * 根据资源id删除资源（逻辑删除）
     *
     * @param id
     * @return
     */
    @Override
    public ResponseEntity deleteById(String id) {
        //为了避免产生缓存击穿，把删除替换为设置空值（很短的过期时间）
        redisTemplate.opsForValue().set(id, null, 5L);
        Integer delResource = resourcesMapper.delResource(id);
        if (delResource > 0) {
            return ResponseEntity.tipsSuccess(200, "删除成功");
        }
        return ResponseEntity.tipsSuccess(500, "系统故障");
    }

}
